package com.pai4j.common.service.localcache;

import com.google.common.cache.Cache;
import com.pai4j.common.enums.messagequeue.MessageBroadChannelEnum;
import com.pai4j.common.service.messagequeue.producer.MessageQueueProducer;
import com.pai4j.domain.dto.queue.RefreshLocalCacheMessage;
import org.springframework.beans.factory.annotation.Autowired;

public abstract class AbstractLocalCacheService<K> implements LocalCacheInter<K> {

    @Autowired
    private MessageQueueProducer<RefreshLocalCacheMessage<K>, Long> messageQueueProducer;

    /**
     * 广播频道
     *
     * @return
     */
    protected abstract MessageBroadChannelEnum getChannel();

    @Override
    public Cache<K, Object> getCache(String cacheObjectName) {

        return null;
    }

    /**
     * 统一实现缓存刷新（走的本地缓存删除动作）
     *
     * 策略：直接删除本地
     *      读: localCache > redis > Mysql
     *      写：Mysql > redis > localCache
     * 所以当本地缓存被删除后，是可以优先从redis中读取到最新数据，同时读取场景会主动刷会本地缓存
     *
     * @param key
     * @param cacheObjectName
     */
    @Override
    public void refreshCache(K key, String cacheObjectName) {
        Cache<K, Object> cache = this.getCache(cacheObjectName);
        if (cache != null) {
            // 直接删除本地
            cache.invalidate(key);
        }
    }


    /**
     * 走MQ 广播/redis pub、sub刷新集群所有节点本地缓存
     *
     * @param
     * @return
     */
    public void doSendRefreshLocalCacheMessage(K key, String cacheObjectName) {
        RefreshLocalCacheMessage<K> message = new RefreshLocalCacheMessage<K>();
        message.setKey(key);
        message.setKeyClazz(key.getClass());
        message.setCacheName(cacheObjectName);
        messageQueueProducer.broadSend(this.getChannel(), message);
    }

}
